/*
 * @(#)Storage.java	0.6 09/01/2009
 */
package org.miao.catstorage;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * 仓库猫框架的主控类，是其他程序调用框架功能的接口
 * @author Miao
 * @version 0.6
 * @since 0.1
 */
public class Storage {

    /**
     * 预定义语句存储池
     */
    private StatementPool pool;
    /**
     * 过滤器
     */
    private Filter filter;
    /**
     * 资源文件
     */
    private File resource;
    /**
     * 缓存容量
     */
    private int capacity = 0;
    /**
     * 是否使用缓存
     */
    private boolean cache = false;
    /**
     * 日志
     */
    private static Log log = LogFactory.getLog(Storage.class);

    /**
     * 缺省构造方法
     * @since 0.1
     */
    public Storage() {
    }

    /**
     * 根据资源文件resource构建Storage
     * @param resource 资源文件
     * @since 0.2
     */
    public Storage(File resource) {
        this.resource = resource;
    }

    /**
     * 根据资源文件resource的路径名字符串构建Storage
     * @param resource 路径名字符串
     * @since 0.2
     */
    public Storage(String resource) {
        this.resource = new File(resource);
    }

    /**
     * 仓库猫框架初始化
     * @since 0.1
     */
    public void config() {
        pool = new JsonStatementPool(resource);
        filter = new ClearFilter(new StatementFilter());
        setCache();
        log.info("仓库猫初始化完成");
    }

    /**
     * 设置缓存
     * @since 0.5
     */
    private void setCache() {
        if (cache) {
            Cache<String, String> statementCache = null;
            if (capacity > 0) {
                statementCache = new Cache<String, String>(capacity);
            } else {
                statementCache = new Cache<String, String>();
            }
            FilterCacheProxy proxy = new FilterCacheProxy(statementCache, filter);
            filter = proxy;
            log.info("缓存启动");
        }
    }

    /**
     * 获得语句
     * <p>列表parameters记录了所有查询参数。程序会根据这些参数对预定义语句进行检查。
     * 如果语句中的条件在参数中，则这些条件会被保留，不符合的条件会被删除。</p>
     * @param key 语句Key
     * @param parameters 查询参数
     * @return 处理结果
     * @since 0.1
     */
    public Result get(String key, List<String> parameters) {
        String result = filter(pool.get(key), parameters);
        if (result != null) {
            return new Result(result);
        } else {
            return null;
        }
    }

    /**
     * 获得语句
     * <p>Map对象parameters以参数名作为key，参数值作为value。程序会根据key和value对预定义语句进行检查。
     * 如果语句中的条件在参数中且value有值（非null），则这些条件会被保留，不符合的条件会被删除。</p>
     * @param key 语句Key
     * @param parameters 查询参数
     * @return 处理结果
     * @since 0.1
     */
    public Result get(String key, Map<String, Object> parameters) {
        return get(key, getParameterList(parameters));
    }

    /**
     * 预定义语句过滤
     * @param statement 预定义语句
     * @param parameters 查询参数
     * @return 处理好的语句
     * @since 0.2
     */
    private String filter(String statement, List<String> parameters) {
        if (statement == null) {
            return null;
        } else {
            if (parameters == null) {
                parameters = new ArrayList<String>();
            }
            return filter.filter(statement, parameters);
        }
    }

    /**
     * 根据参数Map生成参数列表
     * @param parameters 参数Map
     * @return 参数列表
     * @since 0.1
     */
    private List<String> getParameterList(Map<String, Object> parameters) {
        List<String> parameterList = new ArrayList<String>();
        if (parameters == null) {
            return parameterList;
        } else {
            Iterator<Entry<String, Object>> iterator = parameters.entrySet().iterator();
            while (iterator.hasNext()) {
                Entry<String, Object> entry = iterator.next();
                if (entry.getValue() != null) {
                    parameterList.add(entry.getKey());
                }
            }
            return parameterList;
        }
    }

    /**
     * 设置语句存储池
     * @param pool 语句存储池
     * @since 0.2
     */
    public void setPool(StatementPool pool) {
        this.pool = pool;
    }

    /**
     * 设置过滤器
     * @param filter 过滤器
     * @since 0.2
     */
    public void setFilter(Filter filter) {
        this.filter = filter;
    }

    /**
     * 设置资源文件
     * @param resource 资源文件
     * @since 0.2
     */
    public void setResource(File resource) {
        this.resource = resource;
    }

    /**
     * 根据资源文件resource的路径名字符串设置资源文件
     * @param resource 路径名字符串
     * @since 0.2
     */
    public void setResource(String resource) {
        this.resource = new File(resource);
    }

    /**
     * 获得资源文件
     * @return 资源文件
     * @since 0.2
     */
    public File getResource() {
        return resource;
    }

    /**
     * 设定缓存空间容量
     * @param capacity 缓存空间容量
     * @since 0.5
     */
    public void setCapacity(int capacity) {
        this.capacity = capacity;
    }

    /**
     * 设定是否使用缓存
     * @param cache 是否使用缓存
     * @since 0.5
     */
    public void setCache(boolean cache) {
        this.cache = cache;
    }
}
